package com.pan.admin.quartz.service.impl;

import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.pan.admin.common.utils.DateUtils;
import com.pan.admin.module.crm.entity.CrmDistributeLoanUser;
import com.pan.admin.quartz.dao.OrgDistributeDao;
import com.pan.admin.quartz.entity.DistributeUser;
import com.pan.admin.quartz.entity.DistributeUserLogic;
import com.pan.admin.quartz.entity.LoanJfExecuteRecord;
import com.pan.admin.quartz.entity.vo.LoanProductVO;
import com.pan.admin.quartz.service.OrgDistributeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 用户分配调度实现类
 * @Author: ghb
 * @Date: 2023/11/17 14:25
 */
@Service
public class OrgDistributeServiceImpl implements OrgDistributeService {

    @Autowired
    OrgDistributeDao orgDistributeDao;

    /**
     * 记录表最后一条记录
     *
     * @param productId   机构ID
     * @param firstUserId 第一个客服ID
     * @return
     */
    @Override
    public LoanJfExecuteRecord getDistributeRecord(Integer productId, Integer firstUserId) {
        LoanJfExecuteRecord getRecord = orgDistributeDao.getDistributeRecord(productId);
        //  不存在，插入记录
        if (ValidParam.isNull(getRecord)) {
            LoanJfExecuteRecord loanJfExecuteRecord = new LoanJfExecuteRecord();
            loanJfExecuteRecord.setLoanProductId(productId);
            loanJfExecuteRecord.setLastUserId(firstUserId);
            loanJfExecuteRecord.setExecuteStatus(1);
            loanJfExecuteRecord.setCreateTime(DateUtils.getNowDate());
            orgDistributeDao.insertDistributeRecord(loanJfExecuteRecord);
            return loanJfExecuteRecord;
        }
        return getRecord;
    }

    /**
     * 获取全部的机构ID
     */
    @Override
    @Transactional(readOnly = true)
    public List<LoanProductVO> listProductId() {
        return orgDistributeDao.listProductId();
    }

    /**
     * 根据机构ID 获取客服ID
     *
     * @param productId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<DistributeUser> listUserId(Integer productId) {
        return orgDistributeDao.listUserId(productId);
    }

    /**
     * 根据机构ID 获取分配用户ID
     *
     * @param productId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<Integer> listDistributeLoanUserId(Integer productId) {
        return orgDistributeDao.listDistributeLoanUserId(productId);
    }

    /**
     * 批量新增
     *
     * @param userList
     * @return
     */
    @Override
    public void batchInsert(List<CrmDistributeLoanUser> userList) {
        List<List<CrmDistributeLoanUser>> lists = CollUtils.partitionList(userList, 100);
        IteratorUtils.array(lists, list -> orgDistributeDao.batchInsert(userList));
    }

    /**
     * 新增执行记录
     *
     * @param loanJfExecuteRecord
     */
    @Override
    public int insertDistributeRecord(LoanJfExecuteRecord loanJfExecuteRecord) {
        return orgDistributeDao.insertDistributeRecord(loanJfExecuteRecord);
    }

    /**
     * 更新执行记录
     *
     * @param loanJfExecuteRecord 甲方机构分配，执行记录
     * @param lastUserId          最后一个用户
     * @param lastLoanUserId      最后一个客服用户
     * @param productId           机构ID
     * @return 结果
     */
    @Override
    public int updateDistributeRecord(LoanJfExecuteRecord loanJfExecuteRecord, Integer lastUserId, Integer lastLoanUserId, Integer productId) {
        //  最后一个客服ID
        loanJfExecuteRecord.setLastUserId(lastUserId);
        //  最后一个用户ID
        loanJfExecuteRecord.setLastLoanUserId(lastLoanUserId);
        //  当前机构ID
        loanJfExecuteRecord.setLoanProductId(productId);
        loanJfExecuteRecord.setCreateTime(DateUtils.getNowDate());
        loanJfExecuteRecord.setExecuteStatus(2);
        return orgDistributeDao.updateDistributeRecord(loanJfExecuteRecord);
    }

    /**
     * 根据从记录表中获取到的最后一个客服id获取客服对象
     *
     * @param userIdList          用户分配集合
     * @param loanJfExecuteRecord 执行记录
     * @return DistributeUser
     */
    @Override
    public DistributeUser getLastCustomerService(List<DistributeUser> userIdList, LoanJfExecuteRecord loanJfExecuteRecord) {
        //  记录的最后一个分配id
        Integer lastUserId = loanJfExecuteRecord.getLastUserId();
        //  最后记录的分配用户索引
        int indexOf = CollUtils.indexOf(userIdList, t -> Eq.object(t.getUserId(), lastUserId));

        //  如果本身用户分配就是最后一个，则判断是否可分发，如果可分发直接返回
        if (CollUtils.isLastIndex(userIdList, indexOf)) {
            //  从头开始搜索找到能够分发客服用户
            for (int i = 0; i < userIdList.size(); i++) {
                DistributeUser nextDistributeUser = userIdList.get(i);
                if (this.hasDistributeUser(nextDistributeUser)) {
                   return nextDistributeUser;
                }
            }
            return null;
        }

        //  搜索下一个可被分配的客服用户
        boolean reset = false;
        for (int i = indexOf + 1; i < userIdList.size(); i++) {
            DistributeUser distributeUser = userIdList.get(i);

            if (this.hasDistributeUser(distributeUser)) {
                return distributeUser;
            }

            //  如果最后一个则重置一次从0开始循环
            if (CollUtils.isLastIndex(userIdList, i)) {
                if (reset) {
                    return null;
                }
                //  标记重置
                i = 0;
                reset = true;
            }
        }
        return null;
    }

    /**
     *  验证是否可分发用户
     *
     *  @param  distributeUser
     *  @return true 可分发
     */
    public boolean hasDistributeUser(DistributeUser distributeUser) {
        //  用户禁用分配状态用户部门被禁用
        if (Eq.objectOr(0, distributeUser.getDistributeUserStatus(), distributeUser.getDistributeDeptStatus())
                //  子公司或者用户被删除则跳过获取下一个
                || Eq.objectOr(2, distributeUser.getDelDeptFlag(), distributeUser.getDelUserFlag())
                //  子公司或者用户状态被禁用则跳过获取下一个
                || Eq.objectOr(1, distributeUser.getUserStatus(), distributeUser.getDeptStatus())) {
            return false;
        }
        return true;
    }

    /**
     * 分配逻辑 将数据组装到 CrmDistributeLoanUser 对象里面
     *
     * @param productId  机构ID
     * @param userId     用户ID
     * @param deptId     部门ID
     * @param loanUserId 客服用户ID
     * @return
     */
    @Override
    public CrmDistributeLoanUser getDistributeLogic(Integer productId, Integer userId, Integer deptId, Integer loanUserId) {
        CrmDistributeLoanUser distributeLoanUser = new CrmDistributeLoanUser();
        distributeLoanUser.setLoanProductId(productId);
        distributeLoanUser.setUserId(userId);
        distributeLoanUser.setDeptId(deptId);
        distributeLoanUser.setLoanUserId(loanUserId);
        distributeLoanUser.setCreateTime(DateUtils.getNowDate());
        return distributeLoanUser;
    }

    /**
     *  顺序分配逻辑
     *
     *  @param   loanUserIdList      用户集合
     *  @param   userIdList          客服集合
     *  @param   nextDistributeUser  可分配的下一个客服
     *  @param   productId           机构ID
     *  @return  DistributeUserLogic
     */
    public DistributeUserLogic getDistributeSequential(List<Integer> loanUserIdList, List<DistributeUser> userIdList, DistributeUser nextDistributeUser, Integer productId) {
        // 存放分配数据
        List<CrmDistributeLoanUser> distributeLoanUserList = new ArrayList<>();

        //  过滤不能分配的客服
        List<DistributeUser> copyDistributeUser = CollUtils.copy(userIdList);
        CollUtils.filter(copyDistributeUser, t -> !this.hasDistributeUser(t));
        if (ValidParam.isEmpty(copyDistributeUser)) {
            return null;
        }

        //  最大用户索引
        Integer maxUserIndex = copyDistributeUser.size();
        // 获取当前分配客服用户索引
        int userIndex = copyDistributeUser.indexOf(nextDistributeUser);
        // 客户用户索引
        int loanUserIndex = 0;

        //  是否首次分配标识
        boolean firstDistribute = false;
        while (loanUserIndex < loanUserIdList.size()) {
            //  如果超出客服用户集合大小，重新从头开始
            if (firstDistribute && userIndex >= maxUserIndex) {
                userIndex = 0;
            }

            //  获取当前客服用户
            DistributeUser distributeUser = copyDistributeUser.get(userIndex);
            //  获取当前待分配客户ID
            Integer loanUserId = loanUserIdList.get(loanUserIndex);

            // 执行分配逻辑, 将客户用户 分配给 客服用户
            CrmDistributeLoanUser distributeLoanUser = getDistributeLogic(productId, distributeUser.getUserId(), distributeUser.getDeptId(), loanUserId);
            distributeLoanUserList.add(distributeLoanUser);
            loanUserIndex++;
            userIndex++;
            firstDistribute = true;
        }

        //  获取最后分配的记录
        CrmDistributeLoanUser lastDistributeLoanUser = IteratorUtils.getLast(distributeLoanUserList);

        DistributeUserLogic distributeUserLogic = new DistributeUserLogic();
        distributeUserLogic.setDistributeLoanUserList(distributeLoanUserList);
        distributeUserLogic.setLastUserId(lastDistributeLoanUser.getUserId());
        distributeUserLogic.setLastLoanUserId(lastDistributeLoanUser.getLoanUserId());
        return distributeUserLogic;
    }

}
